﻿// <copyright file="Player.cs" company="NorthCoast NERO">
//     NorthCoast NERO. All rights reserved.
// </copyright>
// <author>Eric Kociecki</author>
namespace NcnPlayerCheckIn
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using NcnPlayerCheckIn.Controls;

    /// <summary>
    /// Player object class.  Keeps track of all data for a single player.
    /// </summary>
    public class Player
    {
        /// <summary>
        /// This is the underlying object for the Discounts property.  It should not be accessed except by the Discounts property.
        /// </summary>
        private Collection<DiscountType> discountsHidden;

        /// <summary>
        /// Initializes a new instance of the Player class.
        /// </summary>
        public Player()
        {
        }

        /// <summary>
        /// Gets or sets a link to the PlayerDisplay UserControl if this Player is currently being displayed.
        /// </summary>
        public PlayerDisplay PlayerDisplayControl { get; set; }

        /// <summary>
        /// Gets or sets the player's real name.
        /// </summary>
        public string PlayerName { get; set; }

        /// <summary>
        /// Gets or sets the player's character name.
        /// </summary>
        public string CharacterName { get; set; }

        /// <summary>
        /// Gets or sets the player's home chapter.  TODO, consider changing this to an enum or array of known (but editable) chapters.
        /// </summary>
        public string HomeChapter { get; set; }

        /// <summary>
        /// Gets or sets the player's total build points.
        /// </summary>
        public int BuildTotal { get; set; }

        /// <summary>
        /// Gets or sets the number of days the player will be PCing.
        /// </summary>
        public int PcDaysCount { get; set; }

        /// <summary>
        /// Gets or sets the number of days the player will be NPCing.
        /// </summary>
        public int NpcDaysCount { get; set; }

        /// <summary>
        /// Gets or sets the cost to this player for the event.  This is calculated based on the number of PC and NPC days, any relevant discounts, and any used game-day credits.
        /// </summary>
        public int EventFee { get; set; }

        /// <summary>
        /// Gets any relevant discounts for this player.
        /// </summary>
        public Collection<DiscountType> Discounts
        {
            get
            {
                // lazy loading
                if (this.discountsHidden == null)
                {
                    this.discountsHidden = new Collection<DiscountType>(new List<DiscountType>());
                }

                return this.discountsHidden;
            }

            private set
            {
                this.discountsHidden = value;
            }
        }

        /// <summary>
        /// Gets a string representation of all current Discounts for this player.
        /// </summary>
        public string DiscountsText
        {
            get
            {
                string result = string.Empty;

                foreach (DiscountType dt in this.Discounts)
                {
                    if (!string.IsNullOrWhiteSpace(result))
                    {
                        result += ", ";
                    }

                    result += dt.ToString();
                }

                return result;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the player has checked out from the event.
        /// </summary>
        public bool HasCheckedOut { get; set; }

        /// <summary>
        /// Gets or sets any notes pertaining to the player that are not covered elsewhere.
        /// </summary>
        public string Notes { get; set; }

        /// <summary>
        /// Gets the player's character level based on the set build total.
        /// </summary>
        public int CharacterLevel
        {
            get
            {
                return (int)((this.BuildTotal - 5) / 10);
            }
        }

        /// <summary>
        /// Checks the Player object for valid data and acts as a basic sanity check for player data.  Errors include (but are not limited to) incomplete data, out-of-range values, 
        /// </summary>
        /// <returns>True if data passes all checks, false otherwise.</returns>
        public bool IsValid()
        {
            return !(string.IsNullOrWhiteSpace(this.PlayerName) ||
                string.IsNullOrWhiteSpace(this.CharacterName) ||
                string.IsNullOrWhiteSpace(this.HomeChapter) ||
                ((this.PcDaysCount > 0) && (this.BuildTotal < 30)) || (this.BuildTotal > 1000) || // if the player is PCing, they must have at least 30 build, TODO make this be the equivalent of level 100
                (this.PcDaysCount < 0) || (this.NpcDaysCount < 0) ||
                ((this.PcDaysCount + this.NpcDaysCount) < 1) || // they need to be either PCing or NPCing for at least one day
                ((this.PcDaysCount + this.NpcDaysCount) > 10) || // this accomodates a Cinci 10-day event, but makes no distinction between fully-PCing, fully-NPCing, or splitting the time
                (this.EventFee < 0) || (this.EventFee > 500)); // this accomodates a $50 per day event that lasts for 10 days
        }

        /// <summary>
        /// Resets Player object back to default values.
        /// </summary>
        public void Clear()
        {
            this.PlayerName = string.Empty;
            this.CharacterName = string.Empty;
            this.HasCheckedOut = false;
            this.HomeChapter = string.Empty;
            this.BuildTotal = 0;
            this.PcDaysCount = 0;
            this.Notes = string.Empty;
            this.NpcDaysCount = 0;
            this.Discounts = null;
            this.EventFee = 0;
        }

        /// <summary>
        /// Override of the default ToString method.  It creates a string summary of the player data.
        /// </summary>
        /// <returns>A string summary of the player data.</returns>
        public override string ToString()
        {
            return string.Format(
                    CultureInfo.CurrentCulture,
                    "{0},  {1},  {2},  Build: {3},  Level: {4},  Number of PC Days: {5},  Number of NPC Days: {6},  Event Fee: {7},  Discount: {8},  Notes: {9}",
                    this.PlayerName, // 0
                    this.CharacterName, // 1
                    this.HomeChapter, // 2
                    this.BuildTotal, // 3
                    this.CharacterLevel, // 4
                    this.PcDaysCount, // 5
                    this.NpcDaysCount, // 6
                    this.EventFee, // 7
                    this.DiscountsText, // 8
                    this.Notes); // 9
        }
    }
}
